为艺术而技术

Spring Cloud without Zuul Ribbon and Hystrix

January 13, 2022

注: 如果只想看代码,请移步这里

上次说到,2021版本的Spring Cloud出于netflix不再开源新版本组件而被迫放弃对Zuul,Ribbon以及部分Hystrix,那么我们尝试下在没有他们的情况下升级piggymetrics。也就是基于Spring所推荐的替代品列表:

当前组件 替代品
Hystrix Resilience4j
Hystrix Dashboard / Turbine Micrometer + Monitoring System
Ribbon Spring Cloud Loadbalancer
Zuul 1 Spring Cloud Gateway
Archaius 1 Spring Boot external config + Spring Cloud Config

第一步是抛弃所有应该抛弃Hystrix的库,也就是如下几个:

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        <version>${spring-cloud-netflix-hystrix.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-netflix-hystrix-stream</artifactId>
        <version>${spring-cloud-netflix-hystrix.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        <version>${spring-cloud-netflix-hystrix.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        <version>${spring-cloud-netflix-hystrix.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-turbine-stream</artifactId>
        <version>${spring-cloud-netflix-hystrix.version}</version>
    </dependency>

事情并没有太糟糕,只有Gateway和TubineStream两个子项目编译不能通过,显然是由于@EnableZuulProxy@EnableTurbineStream两个注解失效。而且由于后台都去除了spring-cloud-netflix-hystrix-stream,自然也失去了向RabitMQ发消息的功能。当然也没有了Ribbon所带来的好处。最重要的是要先解决Zuul的问题,这样系统才能跑起来,也就是要动用Spring Gateway和Spring LB了。在之前,启动的时候还遇到下面的错误:

java.lang.IllegalStateException: Annotation @EnableCircuitBreaker found, but there are no implementations. Did you forget to include a starter?
	at org.springframework.cloud.commons.util.SpringFactoryImportSelector.selectImports(SpringFactoryImportSelector.java:77) ~[spring-cloud-commons-3.1.0.jar:3.1.0]

很显然,@EnableCircuitBreaker也是因为只支持hystrix而变成了行尸走肉,需要去除。

Spring Circuit Breaker / Feign

加上如下依赖:

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
    </dependency>

删去部分:

feign:
  hystrix:
    enabled: true

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 10000    

增加部分:

spring:
  cloud:
    circuitbreaker:
      resilience4j:
        enabled: true

feign:
  circuitbreaker:
    enabled: true

再增加一个默认Circuit Breaker的默认配置(不确定系统自带默认配置)

	@Bean
	public Customizer<Resilience4JCircuitBreakerFactory> defaultCustomizer() {
	    return factory -> factory.configureDefault(id -> new Resilience4JConfigBuilder(id)
	            .timeLimiterConfig(TimeLimiterConfig.custom().timeoutDuration(Duration.ofSeconds(4)).build())
	            .circuitBreakerConfig(CircuitBreakerConfig.ofDefaults())
	            .build());
	}

其他代码不用动,依然是Fallback模式。

另外,在notification的项目中,由于用到了@RefreshScope,所以要显式地增加如下配置(默认是disabled),

feign:
  client:
    refresh-enabled: true

Spring Load Balancer

加上如下依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-loadbalancer</artifactId>
    </dependency>

Spring Gateway

加上如下依赖

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>

配置调整比较大

删除部分

ribbon:
  ReadTimeout: 60000
  ConnectTimeout: 60000
  eureka:
    enable: true  

zuul:
  ignoredServices: '*'
  host:
    connect-timeout-millis: 60000
    socket-timeout-millis: 60000

  routes:
    account-service: /accounts/**

    auth-service:
        path: /uaa/**
        url: http://localhost:5000

    statistics-service: /statistics/**

    notification-service:
        path: /notifications/**
        serviceId: notification-service
        stripPrefix: false
        sensitiveHeaders:

增加部分

spring:
  cloud:
    loadbalancer:
      ribbon: 
        enabled: false   
    gateway:
      routes:
      - id: account-service
        uri: lb://account-service
        predicates:
        - Path=/accounts/**
      - id: auth-service
        uri: http://localhost:5000
        predicates:
        - Path=/uaa/**
      - id: statistics-service
        uri: lb://statistics-service
        predicates:
        - Path=/statistics/**
      - id: notification-service
        uri: lb://notification-service
        predicates:
        - Path=/notifications/** 

基于上面的更改,调用前几步都成功了,至此,使用新版本大功告成。


© 2019 - 2022 yuanqingfei
Creative Commons License